﻿using System;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Cors.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using CheryABP.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Castle.Facilities.Logging;
using Swashbuckle.AspNetCore.Swagger;
using Abp.AspNetCore;
using Abp.Castle.Logging.Log4Net;
using Abp.Extensions;
using CheryABP.Configuration;
using CheryABP.Identity;

using Abp.AspNetCore.SignalR.Hubs;
using Microsoft.Extensions.PlatformAbstractions;
using System.IO;
using Abp.EntityFrameworkCore;
using CheryABP.AdoContext;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using CheryABP.Middleware;

namespace CheryABP.Web.Host.Startup
{
    public class Startup
    {
        private const string _defaultCorsPolicyName = "localhost";
        private readonly IConfiguration Configuration;
        private readonly IConfigurationRoot _appConfiguration;

        public Startup(IHostingEnvironment env, IConfiguration configuration)
        {
            _appConfiguration = env.GetAppConfiguration();
            Configuration = configuration;
        }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            //注入session
            services.AddSession();
            //Configure DbContext
            services.AddAbpDbContext<CheryABPDbContext>(options =>
            {
                CheryABPDbContextConfigurer.Configure(options.DbContextOptions, options.ConnectionString);
            });
            // MVC
            //services.AddMvc(
            //    options => options.Filters.Add(new CorsAuthorizationFilterFactory(_defaultCorsPolicyName))
            //);

            IdentityRegistrar.Register(services);
            AuthConfigurer.Configure(services, _appConfiguration);

            services.AddSignalR();
          
            services.AddOptions();

            // 直连 Sql数据库连接地址
            SqlServerConn.CheryABPSql_connString = Configuration.GetConnectionString("CheryABPSQLDataBase");
            //MySql数据库连接地址
            MySqlConn.CheryABPMySql_connString = Configuration.GetConnectionString("CheryABPMySQLDataBase");
            services.AddMvc()
           .AddJsonOptions(json => {
               json.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";//统一设置JsonResult中的日期格式    
           });
            services.AddMvc()
             .AddJsonOptions(options => options.SerializerSettings.ContractResolver
             = new Newtonsoft.Json.Serialization.DefaultContractResolver());//JSON首字母小写解决
            services.AddMvc(options =>
            {
                options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
            });
            //Configure CORS for angular2 UI

           services.AddCors(
               options => options.AddPolicy(
                   _defaultCorsPolicyName,
                   builder => builder
                       .WithOrigins(
                           // App:CorsOrigins in appsettings.json can contain more than one address separated by comma.
                           _appConfiguration["App:CorsOrigins"]
                               .Split(",", StringSplitOptions.RemoveEmptyEntries)
                               .Select(o => o.RemovePostFix("/"))
                               .ToArray()
                       )
                       .AllowAnyHeader()
                       .AllowAnyMethod()
                       .AllowCredentials()
               )
           );

           // Swagger - Enable this line and the related lines in Configure method to enable swagger UI
           services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new Info { Title = "CheryABP API", Version = "v1" });
                var basePath = PlatformServices.Default.Application.ApplicationBasePath;
                var xmlPath = Path.Combine(basePath, "CheryABP.Application.xml");
                options.IncludeXmlComments(xmlPath);
                options.DocInclusionPredicate((docName, description) => true);
                // Define the BearerAuth scheme that's in use
                options.AddSecurityDefinition("bearerAuth", new ApiKeyScheme()
                {
                    Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    In = "header",
                    Type = "apiKey"
                });
            });
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            // Configure Abp and Dependency Injection
            return services.AddAbp<CheryABPWebHostModule>(
                // Configure Log4Net logging
                options => options.IocManager.IocContainer.AddFacility<LoggingFacility>(
                    f => f.UseAbpLog4Net().WithConfig("log4net.config")
                )
            );
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseAbp(options => { options.UseAbpRequestLocalization = false; }); // Initializes ABP framework.

           app.UseCors(_defaultCorsPolicyName); // Enable CORS!

            app.UseStaticFiles();
            app.UseSession(new SessionOptions() { IdleTimeout = TimeSpan.FromDays(1) });
            app.UseAuthentication();

            app.UseAbpRequestLocalization();
            app.UseInterceptMiddleware();//自定义拦截器

            app.UseSignalR(routes =>
            {
                routes.MapHub<AbpCommonHub>("/signalr");
            });

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "defaultWithArea",
                    template: "{area}/{controller=Home}/{action=Index}/{id?}");

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

            // Enable middleware to serve generated Swagger as a JSON endpoint
            app.UseSwagger();
            // Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint(_appConfiguration["App:ServerRootAddress"].EnsureEndsWith('/') + "swagger/v1/swagger.json", "CheryABP API V1");
                options.IndexStream = () => Assembly.GetExecutingAssembly()
                    .GetManifestResourceStream("CheryABP.Web.Host.wwwroot.swagger.ui.index.html");
            }); // URL: /swagger
        }
    }
}
